﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using YasharEl.Infrastructure.EntityModel;

namespace YasharEl.Infrastructure.Core.Personification
{
    [Serializable]
    public class IsraelIdentityNumber : ValueObject<IsraelIdentityNumber>
    {
        #region Fields

        private readonly long _identityNumber;

        #endregion

        #region Constructors

        public IsraelIdentityNumber(long identityNumber)
        {
            _identityNumber = identityNumber;
        }

        #endregion

        #region Properties

        public long IdentityNumber
        {
            get { return _identityNumber; }
        }

        #endregion

        #region Static Methods

        public static IsraelIdentityNumber Parse(string identityNumber)
        {
            if (string.IsNullOrWhiteSpace(identityNumber))
            {
                throw new InvalidIsraelIdentityNumberException(identityNumber);
            }
            if (identityNumber.Length > 9)
            {
                throw new InvalidIsraelIdentityNumberException(identityNumber);
            }

            StringBuilder id = new StringBuilder();

            long[] identityNumberDigits = new long[9];
            long[] identityMultiplyResults = new long[9];
            long[] identitySumOfDigitsResults = new long[9];

            foreach (char identityNumberDigit in identityNumber)
            {
                if (!Char.IsDigit(identityNumberDigit))
                {
                    throw new InvalidIsraelIdentityNumberException(identityNumber);
                }
                id.Append(identityNumberDigit);
            }

            int complementaryZerosCount = 9 - identityNumber.Length;
            if (complementaryZerosCount > 0)
            {
                for (int i = 0; i < complementaryZerosCount; i++)
                {
                    id.Insert(0, "0");
                }
            }

            for (int i = 0; i < 9; i++)
            {
                identityNumberDigits[i] = long.Parse(id[i].ToString());
                if ((i + 1) % 2 == 1)
                {
                    identityMultiplyResults[i] = identityNumberDigits[i] * 1;
                }
                else
                {
                    identityMultiplyResults[i] = identityNumberDigits[i] * 2;
                }
            }

            for (int i = 0; i < 9; i++)
            {
                string identityMultiplyResult = identityMultiplyResults[i].ToString();
                long sum = 0;
                Array.ForEach(identityMultiplyResult.ToCharArray(),
                    (c) => sum += long.Parse(c.ToString())
                );

                identitySumOfDigitsResults[i] = sum;
            }

            long allIdentitySumOfDigitsResultsSummary = 0;
            Array.ForEach<long>(identitySumOfDigitsResults, (s) => allIdentitySumOfDigitsResultsSummary += s);

            if (allIdentitySumOfDigitsResultsSummary % 10 != 0)
            {
                throw new InvalidIsraelIdentityNumberException(identityNumber);
            }

            string idWithouStartingZeros = id.ToString().TrimStart(new char[] { '0' });
            long result = 0;
            long inc = 1;
            for (int i = idWithouStartingZeros.Length - 1; i >= 0; i--)
            {
                result += int.Parse(idWithouStartingZeros[i].ToString()) * inc;
                inc *= 10;
            }

            return new IsraelIdentityNumber(result);
        }

        #endregion

        #region Object Overrides

        public override string ToString()
        {
            return IdentityNumber.ToString();
        }

        #endregion
    }
}
